<?php
/**
 * CreateUser: zlh
 * CreateTime: 2022/1/28 14:34
 * Remark:
 */

namespace App\Http\Middleware\Login;

use App\Consts\BaseConsts\BaseConsts;
use App\Consts\RequestConsts\RequestMethodConsts;
use App\Consts\ResponseConsts\ResponseStatusConsts;
use App\Func\EncryptionFunc;
use App\Func\ResponseFunc;
use App\Func\TokenFuc;
use App\Models\Staff\StaffModel;
use Closure;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Redis;
use JetBrains\PhpStorm\ArrayShape;

class LoginLegitimacyMiddleware
{
    private StaffModel $_staffModel;

    public function __construct()
    {
        $this->_staffModel = new StaffModel();
    }

    public function handle($request, Closure $next)
    {
        $method = strtolower($request->method());
        switch ($method){
            case RequestMethodConsts::GET_METHOD:
                if($request['dto']){
                    $staffId = Redis::get($request['dto']);
                    //校验staffId是否存在
                    $staffInfo = $this->verifyStaff($staffId);
                    $request['staffInfo'] = $staffInfo;
                }
                break;
            case RequestMethodConsts::POST_METHOD:
                // 登录时校验用户名密码是否正确
                if($request['staff_login_account']){
                    $descryData = $this->verifySign();
                    $request['staffId'] = $this->verifyStaffAccount($descryData['staff_login_account'],$descryData['company_id'],$descryData['staff_login_password']);
                }
              break;
            default:
                break;
        }
        return $next($request);
    }

    #[ArrayShape(['staff_login_account' => "bool|string", 'staff_login_password' => "bool|string", 'company_id' => "bool|string"])]
    private function verifySign(): array
    {
        if(time() - (int)microtime(true)*1000 > 60000){
            throw new HttpResponseException( ResponseFunc::returnJson(
                'error',
                null,
                "登录过期",
                ResponseStatusConsts::OK_200_RESPONSE_STATUS,
            ));
        }
        $data = request()->all();
        $sign = EncryptionFunc::getLoginSign(
            $data['staff_login_account'] ?? "",
            $data['staff_login_password'] ?? "",
            $data['company_id'] ?? "",
            $data['timestamp'] ?? "",
        );
        if($sign != $data['sign']){
            throw new HttpResponseException( ResponseFunc::returnJson(
                'error',
                null,
                "签名不匹配",
                ResponseStatusConsts::OK_200_RESPONSE_STATUS,
            ));
        }
        $ivAccount = EncryptionFunc::getOpensslIv(1,$data['timestamp']);
        $ivPwd = EncryptionFunc::getOpensslIv(2,$data['timestamp']);
        $ivCompanyId = EncryptionFunc::getOpensslIv(3,$data['timestamp']);
        return [
            'staff_login_account' => EncryptionFunc::decryptOpenssl($data['staff_login_account'],$ivAccount),
            'staff_login_password' => EncryptionFunc::decryptOpenssl($data['staff_login_password'],$ivPwd),
            'company_id' => EncryptionFunc::decryptOpenssl($data['company_id'],$ivCompanyId)
        ];
    }

    /**
     * @param $staffId
     * @return mixed
     */
    private function verifyStaff($staffId){
        // 校验用户是否存在
        $staffInfo = $this->_staffModel->getStaffDetail($staffId);
        if(!$staffInfo){
            throw new HttpResponseException( ResponseFunc::returnJson(
                'error',
                null,
                "退出成功",
                ResponseStatusConsts::OK_200_RESPONSE_STATUS,
            ));
        }
        return $staffInfo;
    }

    /**
     * @param $account
     * @param $pwd
     */
    private function verifyStaffAccount($account,$companyId,$pwd)
    {
        $staffInfo = $this->_staffModel->getStaffPwdByStaffAccount($account,$companyId);
        if(!$staffInfo){
            throw new HttpResponseException( ResponseFunc::returnJson(
                'error',
                null,
                "账号或密码不匹配",
                ResponseStatusConsts::OK_200_RESPONSE_STATUS,
            ));
        }
        if (!(Hash::check($pwd, $staffInfo['staff_login_password']))) {
            throw new HttpResponseException( ResponseFunc::returnJson(
                'error',
                null,
                "账号或密码不匹配",
                ResponseStatusConsts::OK_200_RESPONSE_STATUS,
            ));
        }
        return $staffInfo['staff_id'];
    }
}